package com.example.mypigcar.service;

import cn.hutool.db.sql.Order;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mypigcar.common.exception.InsufficientBalance;
import com.example.mypigcar.common.exception.OrderExpiredException;
import com.example.mypigcar.common.exception.RepeatPaymentException;
import com.example.mypigcar.mapper.*;
import com.example.mypigcar.pojo.dto.EndOrderDTO;
import com.example.mypigcar.pojo.po.*;
import com.example.mypigcar.pojo.vo.AdminOrderListVO;
import com.example.mypigcar.pojo.vo.DetailOrderVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zkw
 * @Description 订单业务层
 * @createTime 2021年07月07日 08:44:00
 */
@Service
@Transactional
public class TOrderServiceImpl implements TOrderService{
    @Resource
    TOrderDao tOrderDao;

    @Resource
    UserService userService;

    @Resource
    UserDao userDao;

    @Resource
    CarDao carDao;

    @Resource
    ReturnImageDao returnImageDao;

    @Resource
    AppointmentDao appointmentDao;
    /**
     * 用户下单
     * @param tOrder 订单类
     * @Description  1.添加订单到数据库
     *               2.修改预约表状态为 1进行中
     * @return boolean
     */
    @Override
    public boolean insert(TOrder tOrder) {
        //添加订单到数据库
        tOrder.setStatus(0);//未付款
        tOrder.setStartTime(new Date());//时间默认
        tOrder.setEndTime(new Date());
        int insert = tOrderDao.insert(tOrder);


        //更新预约单状态
        QueryWrapper<Appointment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", tOrder.getUserId());
        queryWrapper.eq("status", 0);
        Appointment appointment = new Appointment();
        appointment.setUserId(tOrder.getUserId());
        appointment.setStatus(1);
        appointmentDao.update(appointment, queryWrapper);

        return insert>0;
    }

    /**
     * 用户支付订单
     * @param orderId 订单id
     * @param userId 用户id
     * @Description
     * 1.用户下单需要判断余额是否充足
     * 2.扣费用户余额
     * 3.修改订单状态为1 已支付
     * 4.修改预约单状态为 2 已经结束
     * @return
     */
    @Override
    public boolean payOrder(Integer orderId, Integer userId) throws InsufficientBalance, RepeatPaymentException, OrderExpiredException {
        QueryWrapper<TOrder> orderQueryWrapper = new QueryWrapper<>();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("order_id", orderId);
        TOrder order = tOrderDao.selectOne(orderQueryWrapper);//获取订单
        if (order.getStatus()==1){
            throw new RepeatPaymentException("订单已经支付啦");
        }else if (order.getStatus()==2){
            throw new OrderExpiredException("订单已经过期");
        }
        userQueryWrapper.eq("user_id", userId);
        User user = userDao.selectOne(userQueryWrapper);//获取用户
        user.setBalance(new BigDecimal(0).subtract(order.getRentCarExpenses()));
        userService.updateUserBalance(user); //修改余额 余额不足会抛异常，回滚事务
        order.setStatus(1);
        int update = tOrderDao.update(order, orderQueryWrapper);//修改订单状态

        //4.修改预约单状态为: 2已经结束
        QueryWrapper<Appointment> aq = new QueryWrapper<>();
        aq.eq("status", "1");
        aq.eq("user_id", order.getUserId());
        Appointment appointment = new Appointment();
        appointment.setUserId(order.getUserId());
        appointment.setStatus(2);
        appointmentDao.update(appointment, aq);
        return update>0;
    }

    /**
     * 查询用户全部订单
     * @param userId 用户id
     * @Description 1. 查询用户全部订单
     *              2. 筛选出超过半小时的订单，更新状态为  已过期
     * @return List<TOrder>
     */
    @Override
    public List<TOrder> getUserAllOrder(Integer userId) {
        QueryWrapper<TOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);

        //查询是否有过去半小时的订单，是的话就修改成  过期 状态
        List<TOrder> tOrders = tOrderDao.selectList(queryWrapper);
        List<TOrder> collect = tOrders.stream().filter((order) -> {
            if (order.getStatus() == 0) {
                long time = new Date().getTime() - order.getCreateTime().getTime();
                time = time / 1000 / 60;
                if (time >= 30) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        //修改过期订单的订单状态
        for (TOrder tOrder : collect) {
            QueryWrapper<TOrder> updateQuery = new QueryWrapper<>();
            updateQuery.eq("order_id",tOrder.getOrderId());
            tOrder.setStatus(2);
            tOrderDao.update(tOrder,updateQuery);
        }

        //再次查询
        List<TOrder> againSelect = tOrderDao.selectList(queryWrapper);
        return againSelect;

    }

    /**
     * 结束订单
     * @param endOrderDTO 结束订单DTO
     *                    1.修改订单信息，为订单添加 还车时间、还车地点
     *                    2.添加换车图片到还车表中
     *                    3.计算租车时长，添加到数据库中
     *                    4.计算订单费用，插入订单中，并返回包含费用的订单
     *                    5.更新车辆状态为 可用
     * @return Order
     */
    @Override
    public TOrder endOrder(EndOrderDTO endOrderDTO) {
        QueryWrapper<TOrder> oq = new QueryWrapper<>();
        oq.eq("order_id", endOrderDTO.getOrderId());
        TOrder tOrder = tOrderDao.selectOne(oq);
        tOrder.setEndTime(new Date());
        BeanUtils.copyProperties(endOrderDTO, tOrder);
        System.out.println(tOrder+"***");
        //计算租车时长
        long from2 = tOrder.getStartTime().getTime();
        long to2 = tOrder.getEndTime().getTime();
        int hours = (int) ((to2 - from2) / (1000 * 60 * 60));
        System.out.println("两个时间之间的小时差为：" + hours);
        if (hours==0){
            hours=1;
        }
        //计算订单费用
        QueryWrapper<Car> cq = new QueryWrapper<>();
        cq.eq("car_id", tOrder.getCarId());
        Car car = carDao.selectOne(cq);
        BigDecimal expenses = car.getPrice().multiply(new BigDecimal(hours));
        //更新订单
        tOrder.setRentCarExpenses(expenses);  //更新费用
        tOrder.setRentCarTime(hours); //更新租车时长
        //保存订单的更新
        tOrderDao.update(tOrder, oq);
        //保存还车图片
        for (int i = 0; i < endOrderDTO.getReturnImage().length; i++) {
            ReturnImage returnImage = new ReturnImage(endOrderDTO.getOrderId(), endOrderDTO.getReturnImage()[i]);
            returnImageDao.insert(returnImage);
        }
        //更新车辆状态
        car.setStatus(0);
        carDao.update(car,cq);
        return tOrder;
    }

    /**
     * 查询订单信息给管理员端
     * @return AdminOrderListVO
     */
    @Override
    public List<AdminOrderListVO> selectAdminOrderList() {
        return tOrderDao.selectAdminOrderList();
    }

    /**
     * 根据订单号查询订单 还车图片和还车地点
     * @param order_id 订单号
     * @return DetailOrderVO
     */
    @Override
    public DetailOrderVO getDetailOrder(Integer order_id) {
        QueryWrapper<TOrder> tq = new QueryWrapper<>();
        tq.eq("order_id", order_id);
        TOrder tOrder = tOrderDao.selectOne(tq);
        QueryWrapper<ReturnImage> rq = new QueryWrapper<>();
        rq.eq("order_id", order_id);
        List<ReturnImage> returnImage = returnImageDao.selectList(rq);

        String images[] = new String[returnImage.size()];
        for (int i = 0; i < returnImage.size(); i++) {
            images[i] = returnImage.get(i).getUrl();
        }
        DetailOrderVO detailOrderVO = new DetailOrderVO();
        detailOrderVO.setReturnPlace(tOrder.getReturnPlace());
        detailOrderVO.setReturnImage(images);
        return detailOrderVO;
    }
}
